__vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
}
-static void vmx_do_general_protection_fault(struct cpu_user_regs *regs)
-{
- unsigned long eip, error_code;
- unsigned long intr_fields;
-
- __vmread(GUEST_RIP, &eip);
- __vmread(VM_EXIT_INTR_ERROR_CODE, &error_code);
-
- VMX_DBG_LOG(DBG_LEVEL_1,
- "vmx_general_protection_fault: eip = %lx, erro_code = %lx",
- eip, error_code);
-
- VMX_DBG_LOG(DBG_LEVEL_1,
- "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
- (unsigned long)regs->eax, (unsigned long)regs->ebx,
- (unsigned long)regs->ecx, (unsigned long)regs->edx,
- (unsigned long)regs->esi, (unsigned long)regs->edi);
-
- /* Reflect it back into the guest */
- intr_fields = (INTR_INFO_VALID_MASK |
- INTR_TYPE_EXCEPTION |
- INTR_INFO_DELIEVER_CODE_MASK |
- TRAP_gp_fault);
- __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields);
- __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
-}
static void vmx_vmexit_do_cpuid(unsigned long input, struct cpu_user_regs *regs)
{
vmx_do_no_device_fault();
break;
}
- case TRAP_gp_fault:
- {
- vmx_do_general_protection_fault(®s);
- break;
- }
case TRAP_page_fault:
{
__vmread(EXIT_QUALIFICATION, &va);
/*
* Inject #PG using Interruption-Information Fields
*/
- unsigned long intr_fields;
-
- intr_fields = (INTR_INFO_VALID_MASK |
- INTR_TYPE_EXCEPTION |
- INTR_INFO_DELIEVER_CODE_MASK |
- TRAP_page_fault);
- __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields);
- __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, regs.error_code);
+ vmx_inject_exception(v, TRAP_page_fault, regs.error_code);
v->arch.arch_vmx.cpu_cr2 = va;
TRACE_3D(TRC_VMX_INT, v->domain->domain_id, TRAP_page_fault, va);
}
do_nmi(®s, 0);
break;
default:
- printk("unexpected VMexit for exception vector 0x%x\n", vector);
- //__vmx_bug(®s);
+ vmx_reflect_exception(v);
break;
}
break;
return;
}
- intr_fields = (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR
- | highest_vector);
- __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields);
- __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
-
+ vmx_inject_extint(v, highest_vector, VMX_INVALID_ERROR_CODE);
TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0);
break;
case VLAPIC_DELIV_MODE_FIXED:
return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
}
+#define VMX_INVALID_ERROR_CODE -1
+
+static inline int __vmx_inject_exception(struct vcpu *v, int trap, int type,
+ int error_code)
+{
+ unsigned long intr_fields;
+
+ /* Reflect it back into the guest */
+ intr_fields = (INTR_INFO_VALID_MASK | type | trap);
+ if (error_code != VMX_INVALID_ERROR_CODE) {
+ __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
+ intr_fields |= INTR_INFO_DELIEVER_CODE_MASK;
+ }
+
+ __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields);
+ return 0;
+}
+
+static inline int vmx_inject_exception(struct vcpu *v, int trap, int error_code)
+{
+ return __vmx_inject_exception(v, trap, INTR_TYPE_EXCEPTION, error_code);
+}
+
+static inline int vmx_inject_extint(struct vcpu *v, int trap, int error_code)
+{
+ __vmx_inject_exception(v, trap, INTR_TYPE_EXT_INTR, error_code);
+ __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
+
+ return 0;
+}
+
+static inline int vmx_reflect_exception(struct vcpu *v)
+{
+ int error_code, vector;
+
+ __vmread(VM_EXIT_INTR_INFO, &vector);
+ if (vector & INTR_INFO_DELIEVER_CODE_MASK)
+ __vmread(VM_EXIT_INTR_ERROR_CODE, &error_code);
+ else
+ error_code = VMX_INVALID_ERROR_CODE;
+ vector &= 0xff;
+
+#ifndef NDEBUG
+ {
+ unsigned long eip;
+
+ __vmread(GUEST_RIP, &eip);
+ VMX_DBG_LOG(DBG_LEVEL_1,
+ "vmx_reflect_exception: eip = %lx, error_code = %x",
+ eip, error_code);
+ }
+#endif /* NDEBUG */
+
+ vmx_inject_exception(v, vector, error_code);
+ return 0;
+}
+
static inline shared_iopage_t *get_sp(struct domain *d)
{
return (shared_iopage_t *) d->arch.vmx_platform.shared_page_va;